
#include "thread.h"
#include <exception>
#include <glog/logging.h>
int Thread::Init() {
  try {
    runflag_.store(inited);
    runflag_.store(runing);
    pointer2stdthread_.reset(new std::thread(&Thread::run, this));
  } catch (const std::exception &e) {
  }
  return 0;
}

int Thread::Uinit() {
  try {
    runflag_.store(uninit);
    pointer2stdthread_->join();
    pointer2stdthread_.reset(nullptr);
  } catch (const std::exception &e) {
  }
  return 0;
}

Thread::Thread(const int id, ThreadNotifyer pNotify)
    : id_(id), pointer2stdthread_(nullptr), runflag_(uninit),
      customfunction_(nullptr), customargs_(nullptr),
      pointer2control_(pNotify) {}

Thread::~Thread() {}

int Thread::post(FuncType func, std::shared_ptr<void> args) {
  if (customfunction_ == nullptr) {
    LOG(INFO) << "Thread "
              << " ID: " << id_ << " " << this << " Post Event";
    std::unique_lock<std::mutex> ulock(signalmutex_);
    customfunction_ = func;
    customargs_ = args;
  }
  signalcond_.notify_one();
  return 0;
}

int Thread::run() {
  if (runflag_.load() < inited) {
    return -1;
  }
  while (runflag_.load() == runing) {
    FuncType tempFunc;
    std::shared_ptr<void> tempargs(nullptr);
    {
      std::unique_lock<std::mutex> ulock(signalmutex_);
      signalcond_.wait(ulock, [&tempargs, &tempFunc, this] {
        if (customfunction_ != nullptr) {
          tempFunc = customfunction_;
          tempargs = customargs_;
          customfunction_ = nullptr;
          customargs_.reset();
          return true;
        } else {
          return false;
        }
      });
    }
    LOG(INFO) << "Thread: " << id_ << "Start Proc";
    if (tempFunc != nullptr) {
      LOG(INFO) << "Thread: " << id_ << "Not zero";
      if (pointer2control_->pstart != nullptr) {
        pointer2control_->pstart(id_, 1);
      }
      tempFunc(tempargs);
      if (pointer2control_->pstop != nullptr) {
        LOG(INFO) << "Thread: " << id_ << "Start Free";
        pointer2control_->pstop(id_, 2);
      }
    } else {
      LOG(INFO) << "Thread: " << id_ << "Not Copy";
    }
  }
  return 0;
}

int Thread::stop() {
  signalcond_.notify_one();
  return 0;
}
